package cn.xiaopengstack.domain.activity.service.trialcal.node;

import cn.xiaopengstack.domain.activity.model.dto.DiscountCalculateDTO;
import cn.xiaopengstack.domain.activity.model.entity.MarketProductEntity;
import cn.xiaopengstack.domain.activity.model.entity.TrialCalculateEntity;
import cn.xiaopengstack.domain.activity.model.valobj.GroupBuyActivityDiscountVO;
import cn.xiaopengstack.domain.activity.model.valobj.SkuVO;
import cn.xiaopengstack.domain.activity.service.discount.IDiscountCalculateService;
import cn.xiaopengstack.domain.activity.service.trialcal.AbstractGroupBuyMarketSupport;
import cn.xiaopengstack.domain.activity.service.trialcal.factory.DefaultActivityStrategyFactory;
import cn.xiaopengstack.types.enums.ResponseCode;
import cn.xiaopengstack.types.exception.AppException;
import cn.xiaopengstack.types.framework.strategy.tree.StrategyHandler;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;

/**
 * @author jiangyangang
 */
@Component
@Slf4j
public class MarketNode extends AbstractGroupBuyMarketSupport {

    @Resource
    private TagNode tagNode;
    @Resource
    private ErrorNode errorNode;

    @Resource
    private Map<String, IDiscountCalculateService> discountServiceMap;

    @Override
    public StrategyHandler<MarketProductEntity, DefaultActivityStrategyFactory.DynamicContext, TrialCalculateEntity> get(MarketProductEntity param, DefaultActivityStrategyFactory.DynamicContext dynamicContext) throws Exception {
        GroupBuyActivityDiscountVO groupBuyActivityDiscountVO = dynamicContext.getGroupBuyActivityDiscountVO();
        SkuVO skuVO = dynamicContext.getSkuVO();

        if (Objects.isNull(groupBuyActivityDiscountVO) || Objects.isNull(skuVO) || Objects.isNull(dynamicContext.getDeductionPrice())) {
            return errorNode;
        }

        return tagNode;
    }

    @Override
    protected TrialCalculateEntity doApply(MarketProductEntity param, DefaultActivityStrategyFactory.DynamicContext dynamicContext) throws Exception {
        log.info("拼团商品查询试算服务-MarketNode userId:{} requestParameter:{}", param.getUserId(), JSONObject.toJSONString(param));


        GroupBuyActivityDiscountVO groupBuyActivityDiscountVO = dynamicContext.getGroupBuyActivityDiscountVO();
        SkuVO skuVO = dynamicContext.getSkuVO();

        if (Objects.isNull(groupBuyActivityDiscountVO) || Objects.isNull(skuVO)) {
            return route(param, dynamicContext);
        }

        // 计算折扣
        GroupBuyActivityDiscountVO.GroupBuyDiscount groupBuyDiscount = groupBuyActivityDiscountVO.getGroupBuyDiscount();
        IDiscountCalculateService discountCalculateService = discountServiceMap.get(groupBuyDiscount.getMarketPlan());

        if (Objects.isNull(discountCalculateService)) {
            log.info("不存在对应的折扣计算服务, marketPlan:{}", groupBuyDiscount.getMarketPlan());
            throw new AppException(ResponseCode.UNKNOWN_DISCOUNT.getCode(), ResponseCode.UNKNOWN_DISCOUNT.getInfo());
        }

        BigDecimal deductionPrice = discountCalculateService.calculate(DiscountCalculateDTO.builder()
                .userId(param.getUserId())
                .originalPrice(skuVO.getOriginalPrice())
                .groupBuyDiscount(groupBuyDiscount)
                .build());

        dynamicContext.setDeductionPrice(deductionPrice);
        dynamicContext.setPayPrice(skuVO.getOriginalPrice().subtract(deductionPrice));

        return route(param, dynamicContext);
    }

    @Override
    protected void multiLoadData(MarketProductEntity param, DefaultActivityStrategyFactory.DynamicContext dynamicContext) throws Exception {
        // 查询活动商品详情
        CompletableFuture<GroupBuyActivityDiscountVO> groupActivityFuture = CompletableFuture.supplyAsync(() -> activityRepository.queryGroupBuyActivityDiscountVO(param.getSource(), param.getChannel()), threadPoolExecutor);

        // 查询商品SKU详情
        CompletableFuture<SkuVO> skuFuture = CompletableFuture.supplyAsync(() -> activityRepository.querySkuByGoodsId(param.getGoodsId()), threadPoolExecutor);

        CompletableFuture.allOf(groupActivityFuture, skuFuture).join();

        GroupBuyActivityDiscountVO groupBuyActivityDiscountVO = groupActivityFuture.get();
        SkuVO skuVO = skuFuture.get();

        dynamicContext.setSkuVO(skuVO);
        dynamicContext.setGroupBuyActivityDiscountVO(groupBuyActivityDiscountVO);
    }
}
